home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Dev / gcc263-src.lha / gcc-2.6.3 / config / sh / sh.c < prev    next >
C/C++ Source or Header  |  1994-09-09  |  58KB  |  2,526 lines

  1. /* Output routines for GCC for Hitachi Super-H
  2.    Copyright (C) 1993, 1994 Free Software Foundation, Inc.
  3.  
  4.    This file is part of GNU CC.
  5.  
  6.    GNU CC is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    GNU CC is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with GNU CC; see the file COPYING.  If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. /* Contributed by Steve Chamberlain (sac@cygnus.com) */
  22.  
  23. #include <stdio.h>
  24. #include "assert.h"
  25. #include "config.h"
  26. #include "rtl.h"
  27. #include "regs.h"
  28. #include "hard-reg-set.h"
  29. #include "real.h"
  30. #include "insn-config.h"
  31. #include "conditions.h"
  32. #include "insn-flags.h"
  33. #include "tree.h"
  34. #include "output.h"
  35.  
  36. #include "insn-attr.h"
  37. #include "flags.h"
  38. #include "obstack.h"
  39. #include "expr.h"
  40.  
  41. static rtx add_constant ();
  42.  
  43. int pragma_interrupt;
  44. int pragma_trapa;
  45.  
  46. int current_function_anonymous_args;
  47. extern int current_function_pretend_args_size;
  48. extern char *version_string;
  49. extern int flag_traditional;
  50.  
  51. static rtx shiftsyms[32];
  52. struct rtx_def *table_lab;
  53. enum attr_cpu sh_cpu;        /* target cpu */
  54.  
  55. /* Global variables for machine-dependent things. */
  56.  
  57. /* Saved operands from the last compare to use when we generate an scc
  58.    or bcc insn. */
  59.  
  60. rtx sh_compare_op0;
  61. rtx sh_compare_op1;
  62.  
  63. /* Provides the class number of the smallest class containing
  64.    reg number */
  65.  
  66. int regno_reg_class[FIRST_PSEUDO_REGISTER] =
  67. {
  68.   R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
  69.   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
  70.   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
  71.   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
  72.   GENERAL_REGS, PR_REGS, T_REGS, NO_REGS,
  73.   MAC_REGS, MAC_REGS,
  74. };
  75.  
  76. /* Provide reg_class from a letter such as appears in the machine
  77.    description. */
  78.  
  79. enum reg_class reg_class_from_letter[] =
  80. {
  81.   /* a */ NO_REGS, /* b */ NO_REGS, /* c */ NO_REGS, /* d */ NO_REGS,
  82.   /* e */ NO_REGS, /* f */ NO_REGS, /* g */ NO_REGS, /* h */ NO_REGS,
  83.   /* i */ NO_REGS, /* j */ NO_REGS, /* k */ NO_REGS, /* l */ PR_REGS,
  84.   /* m */ NO_REGS, /* n */ NO_REGS, /* o */ NO_REGS, /* p */ NO_REGS,
  85.   /* q */ NO_REGS, /* r */ NO_REGS, /* s */ NO_REGS, /* t */ T_REGS,
  86.   /* u */ NO_REGS, /* v */ NO_REGS, /* w */ NO_REGS, /* x */ MAC_REGS,
  87.   /* y */ NO_REGS, /* z */ R0_REGS
  88. };
  89.  
  90. /* Value is 1 if register/mode pair is acceptable on SH.  Even
  91.    registers can hold DIs and DF values. The rest can only hold
  92.    SI's efficiently  */
  93.  
  94.  
  95. #define REG_ODD \
  96.  (  (1 << (int) QImode)  | (1 << (int) HImode) | (1 << (int) SImode)    \
  97.   | (1 << (int) QFmode)  | (1 << (int) HFmode) | (1 << (int) SFmode)    \
  98.   | (1 << (int) CQImode) | (1 << (int) CHImode)| (1<< (int)DFmode) | (1<<(int)DImode))
  99.  
  100. #define REG_EVEN \
  101.   (REG_ODD | (1 << (int) CSImode) | (1 << (int) SCmode))
  102.  
  103. #define SI_ONLY (1<<(int)SImode)
  104.  
  105. int hard_regno_mode_ok[] =
  106. {
  107.   REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
  108.   REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
  109.   REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
  110.   REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
  111.   REG, 0, SI_ONLY, SI_ONLY,
  112.   SI_ONLY, SI_ONLY
  113. };
  114.  
  115. /* Local label counter, used for constants in the pool and inside
  116.    pattern branches.  */
  117. static int lf = 100;
  118.  
  119.  
  120. /* Number of bytes pushed for anonymous args, used to pass information
  121.    between expand_prologue and expand_epilogue. */
  122. static int extra_push;
  123.  
  124.  
  125.  
  126. void
  127. push (rn)
  128.      int rn;
  129. {
  130.   rtx x ;
  131.   x=  emit_insn (gen_push (gen_rtx (REG, SImode, rn)));
  132.   REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC, 
  133.                gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0);
  134. }
  135.  
  136. void
  137. pop (rn)
  138.      int rn;
  139. {
  140.   rtx x;
  141.   x =  emit_insn (gen_pop (gen_rtx (REG, SImode, rn)));
  142.   REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC, 
  143.                gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0);
  144. }
  145.  
  146.  
  147. /* Adjust the stack and return the number of bytes taken to do it */
  148. static rtx lastreg;
  149. int lastval;
  150. static void
  151. output_stack_adjust (size)
  152.      int size;
  153. {
  154.   if (size)
  155.     {
  156.       rtx val = GEN_INT (size);
  157.       rtx insn;
  158.  
  159.       if (!CONST_OK_FOR_I (size))
  160.     {
  161.       lastreg = gen_rtx (REG, SImode, 3);
  162.       lastval = size;
  163.       emit_insn (gen_movsi (lastreg, val));
  164.       val = lastreg;
  165.  
  166.     }
  167.  
  168.       insn = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, val);
  169.       emit_insn (insn);
  170.     }
  171. }
  172.  
  173.  
  174. /* Generate code to push the regs specified in the mask, and return
  175.    the number of bytes the insns take. */
  176.  
  177. static void
  178. push_regs (mask)
  179.      int mask;
  180. {
  181.   int i;
  182.  
  183.   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
  184.     {
  185.       if (mask & (1 << i))
  186.     {
  187.       push (i);
  188.     }
  189.     }
  190. }
  191.  
  192.  
  193. /* Print an instruction which would have gone into a delay slot after
  194.    an instructiuon, but couldn't because the instruction expanded into a
  195.    sequence where putting the slot insn at the end wouldn't work. */
  196.  
  197. static void
  198. print_slot (insn)
  199.      rtx insn;
  200. {
  201.   final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1);
  202.  
  203.   INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
  204. }
  205.  
  206.  
  207. /* Work out the registers which need to be saved, both as a mask and a
  208.    count.
  209.  
  210.    If doing a pragma interrupt function, then push all regs used by the function,
  211.    and if we call another function (we can tell by looking at PR), make sure that all the
  212.    regs it clobbers are safe too.
  213.  */
  214. static int
  215. calc_live_regs (count_ptr)
  216.      int *count_ptr;
  217. {
  218.   int reg;
  219.   int live_regs_mask = 0;
  220.   int count = 0;
  221.   for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
  222.     {
  223.       if (reg == ARG_POINTER_REGNUM)
  224.     continue;
  225.       if (reg == T_REG)
  226.     continue;
  227.       if (reg == GBR_REG)
  228.     continue;
  229.  
  230.       if (pragma_interrupt && !pragma_trapa)
  231.     {
  232.       /* Need to save all the regs ever live */
  233.       if ((regs_ever_live[reg]
  234.            || (call_used_regs[reg] && regs_ever_live[PR_REG]))
  235.           && reg != 15)
  236.         {
  237.           live_regs_mask |= 1 << reg;
  238.           count++;
  239.         }
  240.     }
  241.       else if (TARGET_SMALLCALL)
  242.     {
  243.       /* Don't need to push anthing, but count the regs which have
  244.          been pushed by the wrapper */
  245.       if (call_used_regs[reg])
  246.         count++;
  247.     }
  248.       else
  249.     {
  250.       /* Only push those regs which are used and need to be saved */
  251.       if (regs_ever_live[reg] && !call_used_regs[reg])
  252.         {
  253.           count++;
  254.           live_regs_mask |= (1 << reg);
  255.         }
  256.     }
  257.     }
  258.  
  259.  
  260.   *count_ptr = count;
  261.   return live_regs_mask;
  262. }
  263.  
  264.  
  265. static int
  266. need_slot (insn)
  267.      rtx insn;
  268. {
  269.   return (insn && !INSN_ANNULLED_BRANCH_P (XVECEXP (insn, 0, 0)));
  270. }
  271.  
  272. /* Print the operand address in x to the stream */
  273.  
  274. void
  275. print_operand_address (stream, x)
  276.      FILE *stream;
  277.      rtx x;
  278. {
  279.   switch (GET_CODE (x))
  280.     {
  281.     case REG:
  282.       fprintf (stream, "@%s", reg_names[REGNO (x)]);
  283.       break;
  284.     case PLUS:
  285.       {
  286.     rtx base = XEXP (x, 0);
  287.     rtx index = XEXP (x, 1);
  288.  
  289.     if (GET_CODE (base) != REG)
  290.       {
  291.         /* Ensure that BASE is a register (one of them must be). */
  292.         rtx temp = base;
  293.         base = index;
  294.         index = temp;
  295.       }
  296.  
  297.     switch (GET_CODE (index))
  298.       {
  299.       case CONST_INT:
  300.         fprintf (stream, "@(%d,%s)",
  301.              INTVAL (index),
  302.              reg_names[REGNO (base)]);
  303.         break;
  304.  
  305.       case REG:
  306.         fprintf (stream, "@(r0,%s)",
  307.              reg_names[MAX (REGNO (base), REGNO (index))]);
  308.  
  309.         break;
  310.  
  311.       default:
  312.         debug_rtx (x);
  313.         abort ();
  314.       }
  315.       }
  316.  
  317.       break;
  318.     case PRE_DEC:
  319.       fprintf (stream, "@-%s", reg_names[REGNO (XEXP (x, 0))]);
  320.       break;
  321.  
  322.     case POST_INC:
  323.       fprintf (stream, "@%s+", reg_names[REGNO (XEXP (x, 0))]);
  324.       break;
  325.  
  326.     default:
  327.       output_addr_const (stream, x);
  328.       break;
  329.     }
  330. }
  331.  
  332. /* Print operand x (an rtx) in assembler syntax to file stream
  333.    according to modifier code.
  334.  
  335.    '.'  print a .s if insn needs delay slot
  336.    '*'  print a local label
  337.    '^'  increment the local label number
  338.    '!'  dump the constant table
  339.    '#'  output a nop if there is nothing to put in the delay slot
  340.    '@'  print rte or rts depending upon pragma interruptness
  341.    'R'  print the next register or memory location along, ie the lsw in
  342.    a double word value
  343.    'O'  print a constant without the #
  344.    'M'  print a constant as its negative
  345.    'N'  print insides of a @++ or @-- o */
  346.  
  347. void
  348. print_operand (stream, x, code)
  349.      FILE *stream;
  350.      rtx x;
  351.      int code;
  352. {
  353.   switch (code)
  354.     {
  355.     case '.':
  356.       if (need_slot (final_sequence))
  357.     fprintf (stream, ".s");
  358.       break;
  359.     case '*':
  360.       fprintf (stream, "LF%d", lf);
  361.       break;
  362.     case '^':
  363.       lf++;
  364.       break;
  365.     case '@':
  366.       if (pragma_interrupt)
  367.     fprintf (stream, "rte");
  368.       else
  369.     fprintf (stream, "rts");
  370.       break;
  371.     case '#':
  372.       /* Output a nop if there's nothing in the delay slot */
  373.       if (dbr_sequence_length () == 0)
  374.     {
  375.       fprintf (stream, "\n\tnop");
  376.     }
  377.       break;
  378.     case 'O':
  379.       output_addr_const (stream, x);
  380.       break;
  381.     case 'M':
  382.       fprintf (asm_out_file, "#%d", -INTVAL (x));
  383.       break;
  384.     case 'N':
  385.       fputs (reg_names[REGNO (XEXP (XEXP (x, 0), 0))], (stream));
  386.       break;
  387.     case 'R':
  388.       /* Next location along in memory or register */
  389.       switch (GET_CODE (x))
  390.     {
  391.     case REG:
  392.       fputs (reg_names[REGNO (x) + 1], (stream));
  393.       break;
  394.     case MEM:
  395.       print_operand_address (stream, XEXP (adj_offsettable_operand (x, 4), 0));
  396.       break;
  397.     }
  398.       break;
  399.     default:
  400.       switch (GET_CODE (x))
  401.     {
  402.     case REG:
  403.       fputs (reg_names[REGNO (x)], (stream));
  404.       break;
  405.     case MEM:
  406.       output_address (XEXP (x, 0));
  407.       break;
  408.     default:
  409.       fputc ('#', stream);
  410.       output_addr_const (stream, x);
  411.       break;
  412.     }
  413.       break;
  414.     }
  415. }
  416.  
  417.  
  418. static int
  419. sextb (x)
  420.   int x;
  421. {
  422.   x &= 0xff;
  423.   if (x > 127)
  424.     {
  425.       x = -256 + x;
  426.     }
  427.   return x;
  428. }
  429.  
  430.  
  431.  
  432. /* Take a move with integer constant source in OPERANDS, see if it can be generated by
  433.    devious shifting.  If so, generate the instruction sequence and return 1, otherwise
  434.    return 0.
  435.  
  436.     OPERANDS[0] Destination register
  437.     OPERANDS[1] Source constant
  438.  
  439.    00000000 00000000 00000000 0NNNNNNNN simple load
  440.    00000000 00000000 00000000 NNNNNNNN0 load and shift by 1
  441.    00000000 00000000 0000000N NNNNNNN00 load and shift by 2
  442.    00000000 00000000 0NNNNNNN 000000000 load and shift by 8
  443.    00000000 0NNNNNNN 00000000 000000000 load and shift by 16
  444.    N0000000 00000000 00000000 00NNNNNNN load and rotate right
  445.  
  446.    11111111 11111111 11111111 1NNNNNNNN simple load
  447.    11111111 11111111 11111111 NNNNNNNN0 load and shift by 1
  448.    11111111 11111111 1111111N NNNNNNN00 load and shift by 2
  449.    11111111 11111111 1NNNNNNN 000000000 load and shift by 8
  450.    11111111 1NNNNNNN 00000000 000000000 load and shift by 16
  451.    N1111111 11111111 11111111 11NNNNNNN load and rotate right
  452.  
  453.    00000000 00000000 00000000 1NNNNNNNN load and zero extend byte
  454.    00000000 00000000 11111111 1NNNNNNNN load and zero extend word
  455.  
  456.  
  457. */
  458.  
  459. static int
  460. synth_constant (operands, mode)
  461.      rtx operands[];
  462.      enum machine_mode mode;
  463. {
  464.   rtx dst;
  465.   int i = INTVAL (operands[1]) & 0xffffffff;
  466.     
  467.   if (CONST_OK_FOR_I (i))
  468.     return 0;
  469.  
  470.   if (TARGET_CLEN0 && mode != QImode)
  471.     return 0;
  472.  
  473.   if (mode != SImode)
  474.     {
  475.       if (reload_in_progress)
  476.     return 0;
  477.       dst = gen_reg_rtx (SImode);
  478.     }
  479.   else
  480.     {
  481.       dst = operands[0];
  482.     }
  483.  
  484.  
  485.   /*  00000000 00000000 11111111 1NNNNNNNN load and zero extend word      */
  486.   if ((i & 0xffffff80) == 0x0000ff80)
  487.     {
  488.       emit_move_insn (dst, GEN_INT (sextb (i)));
  489.       emit_insn (gen_and_ffff (dst, dst));
  490.     }
  491.   /*    00000000 00000000 00000000 1NNNNNNNN load and zero extend byte */
  492.   else if ((i & 0xffffff80) == 0x00000080)
  493.     {
  494.       emit_move_insn (dst, GEN_INT (sextb (i)));
  495.       emit_insn (gen_and_ff (dst, dst));
  496.     }
  497.   /*   00000000 00000000 00000000 NNNNNNNN0 load and shift by 1
  498.        11111111 11111111 11111111 NNNNNNNN0 load and shift by 1 */
  499.   else if ((i & 0xffffff01) == 0
  500.        || (i & 0xffffff01) == 0xffffff00)
  501.     {
  502.       emit_move_insn (dst, GEN_INT (sextb (i >> 1)));
  503.       emit_insn (gen_ashlsi3_n (dst, dst, GEN_INT (1)));
  504.     }
  505.   /*   00000000 00000000 0000000N NNNNNNN00 load and shift by 2
  506.        11111111 11111111 1111111N NNNNNNN00 load and shift by 2*/
  507.   else if ((i & 0xfffffe03) == 0
  508.        || (i & 0xfffffe03) == 0xfffffe00)
  509.     {
  510.       emit_move_insn (dst, GEN_INT (sextb (i >> 2)));
  511.       emit_insn (gen_ashlsi3_n (dst, dst, GEN_INT (2)));
  512.     }
  513.   /*   00000000 00000000 0NNNNNNN 000000000 load and shift by 8
  514.        11111111 11111111 1NNNNNNN 000000000 load and shift by 8 */
  515.  
  516.   else if ((i & 0xffff80ff) == 0
  517.        || (i & 0xffff80ff) == 0xffff8000)
  518.     {
  519.       emit_move_insn (dst, GEN_INT (sextb (i >> 8)));
  520.       emit_insn (gen_ashlsi3_n (dst, dst, GEN_INT (8)));
  521.     }
  522.   /*     00000000 0NNNNNNN 00000000 000000000 load and shift by 16
  523.      11111111 1NNNNNNN 00000000 000000000 load and shift by 16 */
  524.   else if ((i & 0xff80ffff) == 0x00000000
  525.        || (i & 0xff80ffff) == 0xff800000)
  526.     {
  527.       emit_move_insn (dst, GEN_INT (sextb (i >> 16)));
  528.       emit_insn (gen_ashlsi3_n (dst, dst, GEN_INT (16)));
  529.     }
  530.   /*   00000000 00000000 0NNNNNNN 0NNNNNNNN load shift 8 and add */
  531.   else if ((i & 0xffff8080) == 0 && TARGET_CLEN3)
  532.     {
  533.       emit_move_insn (dst, GEN_INT (sextb (i >> 8)));
  534.       emit_insn (gen_ashlsi3_n (dst, dst, GEN_INT (8)));
  535.       emit_insn (gen_addsi3 (dst, dst, GEN_INT (i & 0x7f)));
  536.     }
  537.   else
  538.     return 0;
  539.  
  540.   if (mode == DImode)
  541.     {
  542.       /* Moving from SI to DI, we've got to zero out the high part */
  543.  
  544.       emit_insn (gen_rtx (SET, VOIDmode, 
  545.               gen_rtx (SUBREG, SImode, operands[0], 0),
  546.               dst));
  547.       emit_insn (gen_rtx (SET, VOIDmode,
  548.               gen_rtx (SUBREG, SImode, operands[0], 1),
  549.               const0_rtx));
  550.  
  551.     }
  552.   else if (mode != SImode)
  553.     {
  554.       emit_insn (gen_rtx (SET, VOIDmode, operands[0],
  555.               gen_rtx (SUBREG, mode, dst, 0)));
  556.  
  557.     }
  558.   return 1;
  559. }
  560.  
  561.  
  562. /* Emit code to perform a block move.  Choose the best method.
  563.  
  564.    OPERANDS[0] is the destination.
  565.    OPERANDS[1] is the source.
  566.    OPERANDS[2] is the size.
  567.    OPERANDS[3] is the alignment safe to use.  */
  568.  
  569.  
  570. int
  571. expand_block_move (operands)
  572.      rtx *operands;
  573. {
  574.   int align = INTVAL (operands[3]);
  575.   int constp = (GET_CODE (operands[2]) == CONST_INT);
  576.   int bytes = (constp ? INTVAL (operands[2]) : 0);
  577.   enum machine_mode mode;
  578.  
  579.   /* IF odd then fail */
  580.   if (!constp || bytes <= 0)
  581.     return 0;
  582.  
  583.   /* Don't expand if we'd make the code bigger and we don't want big code */
  584.  
  585.   if (bytes > 8 && TARGET_SMALLCODE)
  586.     return 0;
  587.  
  588.   switch (align)
  589.     {
  590.     case 1:
  591.       mode = QImode;
  592.       break;
  593.     case 2:
  594.       mode = HImode;
  595.       break;
  596.     default:
  597.       mode = SImode;
  598.       align = 4;
  599.     }
  600.  
  601.   if (mode == SImode && constp && bytes < 64 && (bytes % 4 == 0))
  602.     {
  603.       char entry[30];
  604.       tree entry_name;
  605.       rtx func_addr_rtx;
  606.       rtx r4 = gen_rtx (REG, SImode, 4);
  607.       rtx r5 = gen_rtx (REG, SImode, 5);
  608.       sprintf (entry, "__movstr%s%d", GET_MODE_NAME (mode), bytes);
  609.       entry_name = get_identifier (entry);
  610.  
  611.       func_addr_rtx = copy_to_mode_reg (Pmode,
  612.           gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)));
  613.       emit_insn (gen_move_insn (r4, XEXP (operands[0], 0)));
  614.       emit_insn (gen_move_insn (r5, XEXP (operands[1], 0)));
  615.       emit_insn (gen_block_move_real (func_addr_rtx));
  616.       return 1;
  617.     }
  618.   if (mode == SImode && constp && (bytes % 4 == 0))
  619.     {
  620.       tree entry_name;
  621.       rtx func_addr_rtx;
  622.       rtx r4 = gen_rtx (REG, SImode, 4);
  623.       rtx r5 = gen_rtx (REG, SImode, 5);
  624.       rtx r6 = gen_rtx (REG, SImode, 6);
  625.       entry_name = get_identifier ("__movstr");
  626.  
  627.       func_addr_rtx = copy_to_mode_reg (Pmode,
  628.                     gen_rtx (SYMBOL_REF, Pmode,
  629.                       IDENTIFIER_POINTER (entry_name)));
  630.       emit_insn (gen_move_insn (r4, XEXP (operands[0], 0)));
  631.       emit_insn (gen_move_insn (r5, XEXP (operands[1], 0)));
  632.  
  633.       /* r6 controls the size of the move, 16 is decremented from it
  634.      for each 64 bytes moved, then the -ve bit is used as an index into a
  635.      list of move instructions like this:
  636.     
  637.      {
  638.      do {
  639.      *dst++ = *src++;
  640.      *dst++ = *src++;
  641.      *dst++ = *src++;
  642.      ..etc.. 16 in all
  643.      *dst++ = *src++;
  644.      *dst++ = *src++;
  645.      size -= 16;
  646.      } while (size > 0);
  647.     
  648.      switch (size)
  649.      {
  650.      case -15:
  651.      *dst++ = *src++;
  652.      case -14:
  653.      *dst++ = *src++;
  654.      .. etc.. ;
  655.      case -2:
  656.      *dst++ = *src++;
  657.      case -1:
  658.      *dst++ = *src++;
  659.      case 0:
  660.      ;
  661.      }
  662.      }
  663.     
  664.      eg, a 72 byte move would be set up with size(r6) = 14, for one
  665.      iteration through the big while loop, and a switch of -2 for the last part  */
  666.  
  667.       {
  668.     int final_switch = 16 - ((bytes / 4) % 16);
  669.     int while_loop = ((bytes / 4) / 16 - 1) * 16;
  670.     emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch)));
  671.     emit_insn (gen_block_lump_real (func_addr_rtx));
  672.     return 1;
  673.       }
  674.     }
  675.  
  676.   return 0;
  677. }
  678.  
  679. /* Prepare operands for a move define_expand; specifically, one of the
  680.    operands must be in a register.  Take this chance to remove
  681.    addressing modes which can't be coped with very well. */
  682.  
  683. int
  684. prepare_move_operands (operands, mode)
  685.      rtx operands[];
  686.      enum machine_mode mode;
  687. {
  688.   if (!(reload_in_progress || reload_completed)
  689.       && ((!register_operand (operands[0], mode)
  690.        && !register_operand (operands[1], mode))
  691.       || GET_CODE (operands[1]) == PLUS))
  692.     {
  693.       /* copy the source to a register */
  694.       operands[1] = copy_to_mode_reg (mode, operands[1]);
  695.     }
  696.   if ((mode == SImode || mode == HImode || mode == QImode)
  697.       && GET_CODE (operands[1]) == CONST_INT)
  698.     {
  699.       return synth_constant (operands, mode);
  700.     }
  701.   if (mode == DFmode || mode == DImode)
  702.     {
  703.       rtx src = operands[1];
  704.       rtx dst = operands[0];
  705.       rtx insns;
  706.  
  707.       if (src == dst)
  708.     {
  709.       emit_insn (gen_rtx (SET, VOIDmode, dst, src));
  710.       return 1;
  711.     }
  712.  
  713.       if (GET_CODE (src) == REG &&
  714.       REGNO (src) >= FIRST_PSEUDO_REGISTER)
  715.     return 0;
  716.  
  717.       if (GET_CODE (dst) == REG &&
  718.       REGNO (dst) >= FIRST_PSEUDO_REGISTER)
  719.     return 0;
  720.  
  721.       if (push_operand (dst, mode))
  722.     return 0;
  723.  
  724.       if (GET_CODE (src) == CONST_DOUBLE)
  725.     src = force_const_mem (DFmode, src);
  726.  
  727.       if (reload_in_progress)
  728.     {
  729.       if (!(offsettable_memref_p (src) || register_operand (src, mode)))
  730.         return 0;
  731.       if (!(offsettable_memref_p (dst) || register_operand (dst,
  732.                                 mode)))
  733.         return 0;
  734.     }
  735.       start_sequence ();
  736.       if (GET_CODE (operands[0]) != REG
  737.       || !refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0))
  738.     {
  739.       emit_move_insn (operand_subword (dst, 0, 1, mode),
  740.               operand_subword_force (src, 0, mode));
  741.       emit_move_insn (operand_subword (dst, 1, 1, mode),
  742.               operand_subword_force (src, 1, mode));
  743.     }
  744.       else
  745.     {
  746.       emit_move_insn (operand_subword (dst, 1, 1, mode),
  747.               operand_subword_force (src, 1, mode));
  748.       emit_move_insn (operand_subword (dst, 0, 1, mode),
  749.               operand_subword_force (src, 0, mode));
  750.     }
  751.  
  752.       insns = get_insns ();
  753.       end_sequence ();
  754.  
  755.       emit_no_conflict_block (insns, dst, src, 0, src);
  756.       return 1;
  757.     }
  758.  
  759.   return 0;
  760. }
  761.  
  762. /* Prepare the operands for an scc instruction; make sure that the
  763.    compare has been done.  */
  764. rtx
  765. prepare_scc_operands (code)
  766.      int code;
  767. {
  768.   if (GET_CODE (sh_compare_op0) != REG
  769.       || REGNO (sh_compare_op0) != T_REG)
  770.     {
  771.       int newcode = code;
  772.       /* First need a compare insn */
  773.       switch (code)
  774.     {
  775.     case NE:
  776.       newcode = EQ;
  777.       break;
  778.     case LT:
  779.       newcode = GT;
  780.       break;
  781.     case LE:
  782.       newcode = GE;
  783.       break;
  784.     case LTU:
  785.       newcode = GTU;
  786.       break;
  787.     case LEU:
  788.       newcode = GEU;
  789.       break;
  790.     }
  791.       if (newcode != code)
  792.     {
  793.       rtx tmp = sh_compare_op0;
  794.       sh_compare_op0 = sh_compare_op1;
  795.       sh_compare_op1 = tmp;
  796.       code = newcode;
  797.     }
  798.  
  799.       sh_compare_op0 = force_reg (SImode, sh_compare_op0);
  800.       emit_insn (gen_rtx (SET, VOIDmode,
  801.               gen_rtx (REG, SImode, T_REG),
  802.            gen_rtx (code, SImode, sh_compare_op0, sh_compare_op1)));
  803.     }
  804.   return gen_rtx (REG, SImode, T_REG);
  805. }
  806.  
  807.  
  808. /* Functions to output assembly code. */
  809.  
  810. /* Return a sequence of instructions to perform DI or DF move.
  811.  
  812.    Since the SH cannot move a DI or DF in one instruction, we have
  813.    to take care when we see overlapping source and dest registers.
  814.  
  815.  */
  816.  
  817. char *
  818. output_movedouble (insn, operands, mode)
  819.      rtx insn;
  820.      rtx operands[];
  821.      enum machine_mode mode;
  822. {
  823.   rtx dst = operands[0];
  824.   rtx src = operands[1];
  825.  
  826. /*   fprintf (asm_out_file, "! move double \n");
  827.   fprintf (asm_out_file, "! pc %04x\n", insn_addresses[INSN_UID (insn)]);*/
  828.   if (GET_CODE (dst) == MEM
  829.       && GET_CODE (XEXP (dst, 0)) == POST_INC)
  830.     {
  831.       operands[0] = XEXP (XEXP (dst, 0), 0);
  832.       return "mov.l    %R1,@(4,%0)\n\tmov.l    %1,@%0\n\tadd    #8,%0";
  833.     }
  834.   if (register_operand (dst, mode)
  835.       && register_operand (src, mode))
  836.     {
  837.       if (REGNO (src) == MACH_REG)
  838.     return "sts    mach,%0\n\tsts    macl,%R0";
  839.  
  840.       /*
  841.          when mov.d r1,r2 do r2->r3 then r1->r2
  842.          when mov.d r1,r0 do r1->r0 then r2->r1
  843.        */
  844.  
  845.       if (REGNO (src) + 1 == REGNO (dst))
  846.     return "mov    %R1,%R0\n\tmov    %1,%0 ! cra";
  847.       else
  848.     return "mov    %1,%0\n\tmov    %R1,%R0 ! crb";
  849.     }
  850.   else if (GET_CODE (src) == CONST_INT)
  851.     {
  852.       HOST_WIDE_INT val = INTVAL (src);
  853.       int rn = REGNO (operands[0]);
  854.       if (val < 0)
  855.     {
  856.       fprintf (asm_out_file, "\tmov    #-1,r%d\n", rn);
  857.     }
  858.       else
  859.     {
  860.       fprintf (asm_out_file, "\tmov    #0,r%d\n", rn);
  861.     }
  862.  
  863.       fprintf (asm_out_file, "\tmov    #%d,r%d\n", val, rn + 1);
  864.       return "";
  865.     }
  866.   else if (GET_CODE (src) == MEM)
  867.     {
  868.       int ptrreg1 = -1;
  869.       int ptrreg2 = -1;
  870.       int dreg = REGNO (dst);
  871.       rtx inside = XEXP (src, 0);
  872.  
  873.       if (GET_CODE (inside) == REG)
  874.     {
  875.       ptrreg1 = REGNO (inside);
  876.     }
  877.       else if (GET_CODE (inside) == PLUS)
  878.     {
  879.       rtx lhs = XEXP (inside, 0);
  880.       rtx rhs = XEXP (inside, 1);
  881.       if (GET_CODE (lhs) == REG)
  882.         ptrreg1 = REGNO (lhs);
  883.       if (GET_CODE (rhs) == REG)
  884.         ptrreg2 = REGNO (rhs);
  885.     }
  886.       else if (GET_CODE (inside) == LABEL_REF)
  887.     {
  888.       return "mov.l    %1,%0\n\tmov.l    %1+4,%R0";
  889.     }
  890.       else if (GET_CODE (inside) == POST_INC)
  891.     {
  892.       return "mov.l    %1,%0\n\tmov.l    %1,%R0 !mdi\n";
  893.     }
  894.       else
  895.     abort ();
  896.  
  897.       if ((ptrreg1 >= 0 && ptrreg2 >= 0)
  898.       && (dreg == ptrreg1
  899.           || dreg == ptrreg2
  900.           || dreg + 1 == ptrreg1
  901.           || dreg + 1 == ptrreg2))
  902.     {
  903.       /* This move clobbers both index registers,
  904.          calculate the sum in one register.  */
  905.       fprintf (asm_out_file, "    add    %s,%s ! special fix\n",
  906.            reg_names[ptrreg2], reg_names[ptrreg1]);
  907.  
  908.       if (dreg == ptrreg1)
  909.         {
  910.           /* Copy into dreg+1 first.  */
  911.           fprintf (asm_out_file, "    mov.l    @(4,%s),%s\n",
  912.                reg_names[ptrreg1],
  913.                reg_names[dreg + 1]);
  914.  
  915.           fprintf (asm_out_file, "    mov.l    @(%s),%s\n",
  916.                reg_names[ptrreg1],
  917.                reg_names[dreg]);
  918.         }
  919.       else
  920.         {
  921.           /* Copy into dreg first. */
  922.           fprintf (asm_out_file, "    mov.l    @(%s),%s\n",
  923.                reg_names[ptrreg1],
  924.                reg_names[dreg]);
  925.  
  926.           fprintf (asm_out_file, "    mov.l    @(4,%s),%s\n",
  927.                reg_names[ptrreg1],
  928.                reg_names[dreg + 1]);
  929.  
  930.         }
  931.       warning ("generated complex amode");
  932.       return "";
  933.     }
  934.  
  935.       /* Work out the safe way to copy */
  936.       if (dreg == ptrreg1)
  937.     {
  938.       /* Copy into the second half first */
  939.       return "mov.l    %R1,%R0\n\tmov.l    %1,%0 ! cr";
  940.     }
  941.     }
  942.  
  943.   return "mov.l    %1,%0\n\tmov.l    %R1,%R0";
  944. }
  945.  
  946. /* Emit assembly to shift reg by k bits */
  947.  
  948. char *
  949. output_shift (string, reg, k, code)
  950.      char *string;
  951.      rtx reg;
  952.      rtx k;
  953.      int code;
  954.  
  955. {
  956.   int s = INTVAL (k);
  957.   if (s < 0)
  958.     {
  959.       s = -s;
  960.       switch (code)
  961.     {
  962.     case LSHIFTRT:
  963.     case ASHIFTRT:
  964.       code = ASHIFT;
  965.       break;
  966.     case ASHIFT:
  967.       code = ASHIFTRT;
  968.       break;
  969.     default:
  970.       abort ();
  971.     }
  972.     }
  973.   if (code == ASHIFT && s == 31)
  974.     {
  975.       /* Shift left by 31 moving into the t bit, clearing and rotating the other way */
  976.  
  977.       fprintf (asm_out_file, "\trotr    r%d\n", REGNO (reg));
  978.       fprintf (asm_out_file, "\tmov    #0,r%d\n", REGNO (reg));
  979.       fprintf (asm_out_file, "\trotcr    r%d\n", REGNO (reg));
  980.       s = 0;
  981.     }
  982.  
  983.   if (code == LSHIFTRT && s == 31)
  984.     {
  985.       fprintf (asm_out_file, "\trotl    r%d\n", REGNO (reg));
  986.       fprintf (asm_out_file, "\tmov    #0,r%d\n", REGNO (reg));
  987.       fprintf (asm_out_file, "\trotcl    r%d\n", REGNO (reg));
  988.       s = 0;
  989.     }
  990.  
  991.   while (s)
  992.     {
  993.       char *out;
  994.       int d;
  995.  
  996.       if (s >= 16)
  997.     {
  998.       d = 16;
  999.       out = "16";
  1000.     }
  1001.       else if (s >= 8)
  1002.     {
  1003.       d = 8;
  1004.       out = "8";
  1005.     }
  1006.       else if (s >= 2)
  1007.     {
  1008.       d = 2;
  1009.       out = "2";
  1010.     }
  1011.       else
  1012.     {
  1013.       d = 1;
  1014.       out = "";
  1015.     }
  1016.       fprintf (asm_out_file, "\t%s%s\tr%d\n", string, out, REGNO (reg));
  1017.       s -= d;
  1018.     }
  1019.   return "";
  1020. }
  1021.  
  1022.  
  1023. void
  1024. function_epilogue (stream, size)
  1025.      FILE *stream;
  1026.      int size;
  1027. {
  1028.   pragma_interrupt = pragma_trapa = 0;
  1029. }
  1030.  
  1031.  
  1032. /* Return the text of the branch instruction which matches its length
  1033.    attribute.
  1034.  
  1035.    This gets tricky if we have an insn in the delay slot of a branch
  1036.    and the branch needs more than 1 insn to complete. */
  1037.  
  1038. int pending_const_table;
  1039.  
  1040.  /* We can't tell if we need a register as a scratch for the jump
  1041.     until after branch shortening, and then it's too late to allocate a
  1042.     register the 'proper' way.  These instruction sequences are rare
  1043.     anyway, so to avoid always using a reg up from our limited set, we'll
  1044.     grab one when we need one on output. */
  1045.  
  1046. char *
  1047. output_far_jump (insn, op)
  1048.      rtx insn;
  1049.      rtx op;
  1050. {
  1051.   rtx thislab = gen_label_rtx ();
  1052.  
  1053.   if (dbr_sequence_length ())
  1054.     {
  1055.       /* Something to go in what would have been the delay
  1056.      slot if this had been a short branch. Make sure the
  1057.      reg we use to generate the branch target address
  1058.      doesn't conflict */
  1059.  
  1060.       int i;
  1061.       rtx vec[2];
  1062.       vec[0] = thislab;
  1063.  
  1064.       for (i = 0; i < 8; i++)
  1065.     {
  1066.       vec[1] = gen_rtx (REG, SImode, i);
  1067.       if (!reg_referenced_p (vec[1],
  1068.                  PATTERN (XVECEXP (final_sequence, 0, 1))))
  1069.         break;
  1070.     }
  1071.  
  1072.  
  1073.       print_slot (final_sequence);
  1074.       output_asm_insn ("mov.l    %1,@-r15", vec);
  1075.       output_asm_insn ("mov.l    %O0,%1", vec);
  1076.  
  1077.       output_asm_insn ("jmp    @%1 ! 32 xcond", vec);
  1078.       output_asm_insn ("mov.l    @r15+,%1", vec);
  1079.     }
  1080.   else
  1081.     {
  1082.       output_asm_insn ("mov.l    r13,@-r15", 0);
  1083.       output_asm_insn ("mov.l    %O0,r13", &thislab);
  1084.       output_asm_insn ("jmp    @r13 ! 32 zcond", 0);
  1085.       output_asm_insn ("mov.l    @r15+,r13", 0);
  1086.     }
  1087.  
  1088.   output_asm_insn (".align    2", 0);
  1089.   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (thislab));
  1090.   output_asm_insn (".long    %O0", &op);
  1091.   return "";
  1092. }
  1093.  
  1094. char *
  1095. output_branch (logic, insn)
  1096.      int logic;
  1097.      rtx insn;
  1098. {
  1099.   extern rtx recog_operand[];
  1100.   int label = lf++;
  1101.  
  1102.   /*  fprintf (asm_out_file, "! pc %04x\n", insn_addresses[INSN_UID (insn)]);*/
  1103.  
  1104.   switch (get_attr_length (insn))
  1105.     {
  1106.     case 2:
  1107.       /* Simple branch in range -200..+200 bytes */
  1108.       return logic ? "bt%.    %l0" : "bf%.    %l0";
  1109.  
  1110.     case 6:
  1111.       /* Branch in range -4000..+4000 bytes */
  1112.       {
  1113.     rtx oldop = recog_operand[0];
  1114.  
  1115.  
  1116.     if (need_slot (final_sequence))
  1117.       {
  1118.         fprintf (asm_out_file, "\tb%c.s\tLF%d\n", logic ? 'f' : 't',
  1119.              label);
  1120.  
  1121.         print_slot (final_sequence);
  1122.       }
  1123.  
  1124.     else
  1125.       {
  1126.         fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't',
  1127.              label);
  1128.       }
  1129.     recog_operand[0] = oldop;
  1130.  
  1131.     output_asm_insn ("bra    %l0    ! 12 bit cond ", recog_operand);
  1132.     fprintf (asm_out_file, "\tor    r0,r0\n");
  1133.     fprintf (asm_out_file, "LF%d:\n", label);
  1134.       }
  1135.       return "";
  1136.  
  1137.     case 16:
  1138.       /* Branches a long way away */
  1139.       {
  1140.     rtx oldop = recog_operand[0];
  1141.  
  1142.     if (need_slot (final_sequence))
  1143.       {
  1144.         fprintf (asm_out_file, "\tb%c.s\tLF%d\n", logic ? 'f' : 't', label);
  1145.         print_slot (final_sequence);
  1146.  
  1147.       }
  1148.     else
  1149.       {
  1150.         fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
  1151.       }
  1152.  
  1153.     output_far_jump (insn, oldop);
  1154.     fprintf (asm_out_file, "LF%d:\n", label);
  1155.     return "";
  1156.       }
  1157.     }
  1158.   return "bad";
  1159. }
  1160.  
  1161.  
  1162. /* The SH cannot load a large constant into a register, constants have to
  1163.    come from a pc relative load.  The reference of a pc relative load
  1164.    instruction must be less than 1k infront of the instruction.  This
  1165.    means that we often have to dump a constant inside a function, and
  1166.    generate code to branch around it.
  1167.  
  1168.    It is important to minimize this, since the branches will slow things
  1169.    down and make things bigger.
  1170.  
  1171.    Worst case code looks like:
  1172.  
  1173.    mov.l L1,rn
  1174.    bra   L2
  1175.    nop
  1176.    align
  1177.    L1:   .long value
  1178.    L2:
  1179.    ..
  1180.  
  1181.    mov.l L3,rn
  1182.    bra   L4
  1183.    nop
  1184.    align
  1185.    L3:   .long value
  1186.    L4:
  1187.    ..
  1188.  
  1189.    We fix this by performing a scan before scheduling, which notices which
  1190.    instructions need to have their operands fetched from the constant table
  1191.    and builds the table.
  1192.  
  1193.  
  1194.    The algorithm is:
  1195.  
  1196.    scan, find an instruction which needs a pcrel move.  Look forward, find the
  1197.    last barrier which is within MAX_COUNT bytes of the requirement.
  1198.    If there isn't one, make one.  Process all the instructions between
  1199.    the find and the barrier.
  1200.  
  1201.    In the above example, we can tell that L3 is within 1k of L1, so
  1202.    the first move can be shrunk from the 3 insn+constant sequence into
  1203.    just 1 insn, and the constant moved to L3 to make:
  1204.  
  1205.    mov.l        L1,rn
  1206.    ..
  1207.    mov.l        L3,rn
  1208.    bra          L4
  1209.    nop
  1210.    align
  1211.    L3:.long value
  1212.    L4:.long value
  1213.  
  1214.    Then the second move becomes the target for the shortening process.
  1215.  
  1216.  */
  1217.  
  1218. typedef struct
  1219. {
  1220.   rtx value;            /* Value in table */
  1221.   rtx label;            /* Label of value */
  1222.   enum machine_mode mode;    /* Mode of value */
  1223. }
  1224.  
  1225. pool_node;
  1226.  
  1227. /* The maximum number of constants that can fit into one pool, since
  1228.    the pc relative range is 0...1020 bytes and constants are at least 4
  1229.    bytes long */
  1230.  
  1231. #define MAX_POOL_SIZE (1020/4)
  1232. static pool_node pool_vector[MAX_POOL_SIZE];
  1233. static int pool_size;
  1234.  
  1235. /* Add a constant to the pool and return its label.  */
  1236.  
  1237. static rtx
  1238. add_constant (x, mode)
  1239.      rtx x;
  1240.      enum machine_mode mode;
  1241. {
  1242.   int i;
  1243.   rtx lab;
  1244.   /* First see if we've already got it */
  1245.  
  1246.   for (i = 0; i < pool_size; i++)
  1247.     {
  1248.       if (x->code == pool_vector[i].value->code
  1249.       && mode == pool_vector[i].mode)
  1250.     {
  1251.       if (x->code == CODE_LABEL)
  1252.         {
  1253.           if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
  1254.         continue;
  1255.         }
  1256.       if (rtx_equal_p (x, pool_vector[i].value))
  1257.         return pool_vector[i].label;
  1258.     }
  1259.     }
  1260.  
  1261.   /* Need a new one */
  1262.  
  1263.   pool_vector[pool_size].value = x;
  1264.   lab = gen_label_rtx ();
  1265.   pool_vector[pool_size].mode = mode;
  1266.   pool_vector[pool_size].label = lab;
  1267.   pool_size++;
  1268.   return lab;
  1269. }
  1270.  
  1271. /* Dump out interesting debug info */
  1272.  
  1273. void
  1274. final_prescan_insn (insn, opvec, noperands)
  1275.      rtx insn;
  1276.      rtx *opvec;
  1277.      int noperands;
  1278. {
  1279.   if (target_flags & ISIZE_BIT)
  1280.     {
  1281.       extern int *insn_addresses;
  1282.       fprintf (asm_out_file, "\n! at %04x\n",
  1283.            insn_addresses[INSN_UID (insn)]);
  1284.     }
  1285. }
  1286.  
  1287.  
  1288.  
  1289.  
  1290. /* Stuff taken from m88k.c */
  1291.  
  1292. /* Output to FILE the start of the assembler file.  */
  1293.  
  1294. struct option
  1295. {
  1296.   char *string;
  1297.   int *variable;
  1298.   int on_value;
  1299. };
  1300.  
  1301. static int
  1302. output_option (file, sep, type, name, indent, pos, max)
  1303.      FILE *file;
  1304.      char *sep;
  1305.      char *type;
  1306.      char *name;
  1307.      char *indent;
  1308.      int pos;
  1309.      int max;
  1310. {
  1311.   if (strlen (sep) + strlen (type) + strlen (name) + pos > max)
  1312.     {
  1313.       fprintf (file, indent);
  1314.       return fprintf (file, "%s%s", type, name);
  1315.     }
  1316.   return pos + fprintf (file, "%s%s%s", sep, type, name);
  1317. }
  1318.  
  1319. static struct
  1320. {
  1321.   char *name;
  1322.   int value;
  1323. }
  1324.  
  1325. m_options[] = TARGET_SWITCHES;
  1326.  
  1327. static void
  1328. output_options (file, f_options, f_len, W_options, W_len,
  1329.         pos, max, sep, indent, term)
  1330.      FILE *file;
  1331.      struct option *f_options;
  1332.      struct option *W_options;
  1333.      int f_len, W_len;
  1334.      int pos;
  1335.      int max;
  1336.      char *sep;
  1337.      char *indent;
  1338.      char *term;
  1339. {
  1340.   register int j;
  1341.  
  1342.  
  1343.   if (optimize)
  1344.     pos = output_option (file, sep, "-O", "", indent, pos, max);
  1345.   if (write_symbols != NO_DEBUG)
  1346.     pos = output_option (file, sep, "-g", "", indent, pos, max);
  1347.   if (flag_traditional)
  1348.     pos = output_option (file, sep, "-traditional", "", indent, pos, max);
  1349.   if (profile_flag)
  1350.     pos = output_option (file, sep, "-p", "", indent, pos, max);
  1351.   if (profile_block_flag)
  1352.     pos = output_option (file, sep, "-a", "", indent, pos, max);
  1353.  
  1354.   for (j = 0; j < f_len; j++)
  1355.     if (*f_options[j].variable == f_options[j].on_value)
  1356.       pos = output_option (file, sep, "-f", f_options[j].string,
  1357.                indent, pos, max);
  1358.  
  1359.   for (j = 0; j < W_len; j++)
  1360.     if (*W_options[j].variable == W_options[j].on_value)
  1361.       pos = output_option (file, sep, "-W", W_options[j].string,
  1362.                indent, pos, max);
  1363.  
  1364.   for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++)
  1365.     if (m_options[j].name[0] != '\0'
  1366.     && m_options[j].value > 0
  1367.     && ((m_options[j].value & target_flags)
  1368.         == m_options[j].value))
  1369.       pos = output_option (file, sep, "-m", m_options[j].name,
  1370.                indent, pos, max);
  1371.  
  1372.  
  1373.   fprintf (file, term);
  1374.   fprintf (file, "! %d %d\n", max_count_si, max_count_hi);
  1375. }
  1376.  
  1377. void
  1378. output_file_start (file, f_options, f_len, W_options, W_len)
  1379.      FILE *file;
  1380.      struct option *f_options;
  1381.      struct option *W_options;
  1382.      int f_len, W_len;
  1383. {
  1384.   register int pos;
  1385.  
  1386.   output_file_directive (file, main_input_filename);
  1387.  
  1388.   /* Switch to the data section so that the coffsem symbol and the
  1389.      gcc2_compiled. symbol aren't in the text section.  */
  1390.   data_section ();
  1391.  
  1392.  
  1393.   pos = fprintf (file, "\n! Hitachi SH cc1 (%s) (release I-1) arguments:", version_string);
  1394.   output_options (file, f_options, f_len, W_options, W_len,
  1395.           pos, 75, " ", "\n! ", "\n\n");
  1396. }
  1397.  
  1398.  
  1399.  
  1400. /* Return the cost of a shift */
  1401.  
  1402. int
  1403. shiftcosts (RTX)
  1404.      rtx RTX;
  1405. {
  1406.   /* If shift by a non constant, then this will be expensive. */
  1407.   if (GET_CODE (XEXP (RTX, 1)) != CONST_INT)
  1408.     return 20;
  1409.  
  1410.   /* otherwise, it will be very cheap if by one of the constants
  1411.      we can cope with. */
  1412.   if (CONST_OK_FOR_K (INTVAL (XEXP (RTX, 1))))
  1413.     return 1;
  1414.  
  1415.   /* otherwise it will be several insns, but we pretend that it will be more than
  1416.      just the components, so that combine doesn't glue together a load of shifts into
  1417.      one shift which has to be emitted as a bunch anyway - breaking scheduling */
  1418.   return 1;
  1419. }
  1420.  
  1421. int
  1422. andcosts (RTX)
  1423.      rtx RTX;
  1424. {
  1425.   int i;
  1426.   if (GET_CODE (XEXP (RTX, 1)) != CONST_INT)
  1427.     return 2;
  1428.   i = INTVAL (XEXP (RTX, 1));
  1429.   /* And can use the extend insns cheaply */
  1430.   if (i == 0xff || i == 0xffff)
  1431.     return 2;
  1432.   /* Any small constant is reasonably cheap - but requires r0 */
  1433.   if (CONST_OK_FOR_I (i))
  1434.     return 3;
  1435.   return 5;
  1436. }
  1437.  
  1438. int 
  1439. howshift (i)
  1440.      int i;
  1441. {
  1442.   int total = 0;
  1443.   while (i > 0)
  1444.     {
  1445.       if (i >= 16)
  1446.     {
  1447.       total++;
  1448.       i -= 16;
  1449.     }
  1450.       else if (i >= 8)
  1451.     {
  1452.       total++;
  1453.       i -= 8;
  1454.     }
  1455.       else if (i >= 2)
  1456.     {
  1457.       total++;
  1458.       i -= 2;
  1459.     }
  1460.       else if (i >= 1)
  1461.     {
  1462.       total++;
  1463.       i--;
  1464.     }
  1465.     }
  1466.   return total;
  1467. }
  1468.  
  1469. /* Return the cost of a multiply */
  1470. int
  1471. multcosts (RTX)
  1472.      rtx RTX;
  1473. {
  1474.   /* If mult by a power of 2 then work out how we'd shift to make it */
  1475.   int insn_cost = 0;
  1476.  
  1477.   if (GET_CODE (XEXP (RTX, 1)) == CONST_INT)
  1478.     {
  1479.       int i = exact_log2 (INTVAL (XEXP (RTX, 1)));
  1480.       if (i >= 0)
  1481.     insn_cost = howshift (i);
  1482.       else
  1483.     insn_cost = 100000;
  1484.     }
  1485.   if (TARGET_SH2)
  1486.     {
  1487.       /* We have a mul insn, so we can never take more than the mul and the
  1488.      read of the mac reg, but count more because of the latency and extra reg
  1489.      usage */
  1490.       if (TARGET_SMALLCODE)
  1491.     return 2;
  1492.       if (insn_cost > 5)
  1493.     return 5;
  1494.       return insn_cost;
  1495.     }
  1496.  
  1497.   /* If we we're aiming at small code, then just count the number of
  1498.      insns in a multiply call sequence */
  1499.  
  1500.   if (TARGET_SMALLCODE)
  1501.     {
  1502.       if (insn_cost > 6)
  1503.     return 6;
  1504.       return insn_cost;
  1505.     }
  1506.  
  1507.   /* Otherwise count all the insns in the routine we'd be calling too */
  1508.   return 20;
  1509. }
  1510.  
  1511. /* Code to expand a shift */
  1512.  
  1513. void
  1514. gen_ashift (type, n, reg)
  1515.      int type;
  1516.      int n;
  1517.      rtx reg;
  1518. {
  1519.   switch (type)
  1520.     {
  1521.     case ASHIFTRT:
  1522.       emit_insn (gen_ashrsi3_k (reg, reg, GEN_INT (n)));
  1523.       break;
  1524.     case LSHIFTRT:
  1525.       emit_insn (gen_lshrsi3_k (reg, reg, GEN_INT (n)));
  1526.       break;
  1527.     case ASHIFT:
  1528.       if (n == 1)
  1529.     emit_insn (gen_addsi3 (reg, reg, reg));
  1530.       else
  1531.     emit_insn (gen_ashlsi3_k (reg, reg, GEN_INT (n)));
  1532.       break;
  1533.     }
  1534. }
  1535.  
  1536. int
  1537. gen_shifty_op (code, operands)
  1538.      int code;
  1539.      rtx *operands;
  1540. {
  1541.   rtx wrk = gen_reg_rtx (SImode);
  1542.   rtx t;
  1543.   char *func;
  1544.   if (GET_CODE (operands[2]) == CONST_INT)
  1545.     {
  1546.       int value = INTVAL (operands[2]);
  1547.     top:
  1548.       switch (code)
  1549.     {
  1550.     case ASHIFTRT:
  1551.       if (value < 0)
  1552.         {
  1553.           code = ASHIFT;
  1554.           value = -value;
  1555.           goto top;
  1556.         }
  1557.  
  1558.       /* Expand a short sequence inline, longer call a magic routine */
  1559.       if (value <= 5)
  1560.         {
  1561.           emit_move_insn (wrk, operands[1]);
  1562.           while (value--)
  1563.         {
  1564.           gen_ashift (ASHIFTRT, 1, wrk);
  1565.         }
  1566.           emit_move_insn (operands[0], wrk);
  1567.           return 1;
  1568.         }
  1569.       t = gen_reg_rtx (Pmode);
  1570.       /*  Load the value into an arg reg and call a helper */
  1571.       emit_move_insn (gen_rtx (REG, SImode, 4), operands[1]);
  1572.       if (!shiftsyms[value])
  1573.         {
  1574.           func = xmalloc (18);
  1575.           sprintf (func, "__ashiftrt_r4_%d", value);
  1576.           shiftsyms[value] = gen_rtx (SYMBOL_REF, Pmode, func);
  1577.         }
  1578.       emit_move_insn (t, shiftsyms[value]);
  1579.       emit_insn (gen_ashrsi3_n (GEN_INT (value), t));
  1580.       emit_move_insn (operands[0], gen_rtx (REG, SImode, 4));
  1581.       return 1;
  1582.  
  1583.     case ASHIFT:
  1584.       if (value < 0)
  1585.         {
  1586.           code = LSHIFTRT;
  1587.           value = -value;
  1588.           goto top;
  1589.         }
  1590.       /* Fall through */
  1591.     case LSHIFTRT:
  1592.  
  1593.       if (value < 0)
  1594.         {
  1595.           code = ASHIFT;
  1596.           value = -value;
  1597.           goto top;
  1598.         }
  1599.  
  1600.       emit_move_insn (wrk, operands[1]);
  1601.       while (value)
  1602.         {
  1603.           if (value >= 16)
  1604.         {
  1605.           gen_ashift (code, 16, wrk);
  1606.           value -= 16;
  1607.         }
  1608.           else if (value >= 8)
  1609.         {
  1610.           gen_ashift (code, 8, wrk);
  1611.           value -= 8;
  1612.         }
  1613.           else if (value >= 2)
  1614.         {
  1615.           gen_ashift (code, 2, wrk);
  1616.           value -= 2;
  1617.         }
  1618.           else
  1619.         {
  1620.           gen_ashift (code, 1, wrk);
  1621.           value--;
  1622.         }
  1623.         }
  1624.       emit_move_insn (operands[0], wrk);
  1625.       return 1;
  1626.  
  1627.     }
  1628.     }
  1629.   return 0;
  1630. }
  1631.  
  1632. /* Dump out any constants accumulated in the final pass -
  1633.    which will only be labels */
  1634. char *
  1635. output_jump_label_table ()
  1636. {
  1637.   int i;
  1638.   if (pool_size)
  1639.     {
  1640.       fprintf (asm_out_file, "\t.align 2\n");
  1641.       for (i = 0; i < pool_size; i++)
  1642.     {
  1643.       pool_node *p = pool_vector + i;
  1644.  
  1645.       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (p->label));
  1646.       output_asm_insn (".long    %O0", &p->value);
  1647.     }
  1648.       pool_size = 0;
  1649.     }
  1650.  
  1651.   return "";
  1652. }
  1653. /* Output the literal table */
  1654.  
  1655. static void
  1656. dump_table (scan)
  1657.      rtx scan;
  1658. {
  1659.   int i;
  1660.   int need_align = 1;
  1661.  
  1662.  
  1663.   /* Do two passes, first time dump out the HI sized constants */
  1664.  
  1665.   for (i = 0; i < pool_size; i++)
  1666.     {
  1667.       pool_node *p = pool_vector + i;
  1668.       if (p->mode == HImode)
  1669.     {
  1670.       if (need_align)
  1671.         {
  1672.           scan = emit_insn_after (gen_align_2 (), scan);
  1673.           need_align = 0;
  1674.         }
  1675.       scan = emit_label_after (p->label, scan);
  1676.       scan = emit_insn_after (gen_consttable_2 (p->value), scan);
  1677.     }
  1678.     }
  1679.   need_align = 1;
  1680.  
  1681.   for (i = 0; i < pool_size; i++)
  1682.     {
  1683.       pool_node *p = pool_vector + i;
  1684.  
  1685.       switch (p->mode)
  1686.     {
  1687.     case HImode:
  1688.       break;
  1689.     case SImode:
  1690.       if (need_align)
  1691.         {
  1692.           need_align = 0;
  1693.           scan = emit_label_after (gen_label_rtx (), scan);
  1694.           scan = emit_insn_after (gen_align_4 (), scan);
  1695.         }
  1696.       scan = emit_label_after (p->label, scan);
  1697.       scan = emit_insn_after (gen_consttable_4 (p->value), scan);
  1698.       break;
  1699.     case DImode:
  1700.       if (need_align)
  1701.         {
  1702.           need_align = 0;
  1703.           scan = emit_label_after (gen_label_rtx (), scan);
  1704.           scan = emit_insn_after (gen_align_4 (), scan);
  1705.         }
  1706.       scan = emit_label_after (p->label, scan);
  1707.       scan = emit_insn_after (gen_consttable_8 (p->value), scan);
  1708.       break;
  1709.     default:
  1710.       abort ();
  1711.       break;
  1712.     }
  1713.     }
  1714.  
  1715.   scan = emit_insn_after (gen_consttable_end (), scan);
  1716.   scan = emit_barrier_after (scan);
  1717.   pool_size = 0;
  1718. }
  1719.  
  1720.  
  1721.  
  1722. /* Non zero if the src operand needs to be fixed up */
  1723. static
  1724. int
  1725. fixit (src, mode)
  1726.      rtx src;
  1727.      enum machine_mode mode;
  1728. {
  1729.   if (mode == QImode)
  1730.     return 0;            /* QIs never need to be fixed */
  1731.   if (GET_CODE (src) == CONST)
  1732.     return 1;
  1733.  
  1734.   if (GET_CODE (src) == SYMBOL_REF)
  1735.     {
  1736.       return 1;
  1737.     }
  1738.   if (GET_CODE (src) == LABEL_REF)
  1739.     {
  1740.       return 1;
  1741.     }
  1742.   if (GET_CODE (src) == CONST_INT)
  1743.     {
  1744.       /* All QI insns are ok */
  1745.       if (mode == QImode)
  1746.     return 1;
  1747.       /* The rest may need to be fixed */
  1748.       return !CONST_OK_FOR_I (INTVAL (src));
  1749.     }
  1750.   return 0;
  1751. }
  1752.  
  1753. /* Return Non-zero if constant would be an ok source for a
  1754.    mov.w instead of a mov.l */
  1755. int
  1756. hi_const (src)
  1757.      rtx src;
  1758. {
  1759.   if (GET_CODE (src) == CONST
  1760.       && GET_CODE (XEXP (src, 0)) == SIGN_EXTEND
  1761.       && GET_CODE (XEXP (XEXP (src, 0), 0)) == SYMBOL_REF)
  1762.     return 1;
  1763.  
  1764.   if (TARGET_SHORTADDR
  1765.       && GET_CODE (src) == SYMBOL_REF)
  1766.     return 1;
  1767.  
  1768.   return (GET_CODE (src) == CONST_INT
  1769.       && INTVAL (src) >= -32768
  1770.       && INTVAL (src) <= 32767);
  1771. }
  1772.  
  1773. /* Find the last barrier less than MAX_COUNT bytes from FROM, or create one.
  1774.    If an HI move is found, then make sure that MAX_COUNT_HI isn't broken from that one. */
  1775.  
  1776. static
  1777. rtx
  1778. find_barrier (from)
  1779.      rtx from;
  1780. {
  1781.   int count_si = 0;
  1782.   int count_hi = 0;
  1783.   int found_hi = 0;
  1784.   int found_si = 0;
  1785.   rtx found_barrier = 0;
  1786.   while (from
  1787.      && count_si < max_count_si
  1788.      && count_hi < max_count_hi)
  1789.     {
  1790.       int inc;
  1791.       if (GET_CODE (from) == BARRIER)
  1792.     {
  1793.       found_barrier = from;
  1794.     }
  1795.       /* Count the length of this insn - we assume that all moves will
  1796.      be 2 bytes long, except the DIs */
  1797.  
  1798.       if (GET_CODE (from) == INSN &&
  1799.       GET_CODE (PATTERN (from)) == SET)
  1800.     {
  1801.       rtx src = SET_SRC (PATTERN (from));
  1802.       if (hi_const (src))
  1803.         found_hi = 1;
  1804.       else
  1805.         found_si = 1;
  1806.       inc = (GET_MODE_SIZE (GET_MODE (src)) > 4) ? 4 : 2;
  1807.     }
  1808.       else
  1809.     {
  1810.       inc = get_attr_length (from);
  1811.     }
  1812.       if (found_si)
  1813.     count_si += inc;
  1814.       if (found_hi)
  1815.     count_hi += inc;
  1816.       from = NEXT_INSN (from);
  1817.     }
  1818.  
  1819.   if (!found_barrier)
  1820.     {
  1821.       /* We didn't find a barrier in time to 
  1822.      dump our stuff, so we'll make one */
  1823.       rtx label = gen_label_rtx ();
  1824.       /* Walk back to be just before any jump */
  1825.       from = PREV_INSN (from);
  1826.       while (GET_CODE (from) == JUMP_INSN
  1827.          || GET_CODE (from) == NOTE
  1828.          || GET_CODE (from) == CODE_LABEL)
  1829.     {
  1830.       from = PREV_INSN (from);
  1831.     }
  1832.       from = emit_jump_insn_after (gen_jump (label), from);
  1833.       JUMP_LABEL (from) = label;
  1834.       found_barrier = emit_barrier_after (from);
  1835.       emit_label_after (label, found_barrier);
  1836.       return found_barrier;
  1837.     }
  1838.   return found_barrier;
  1839. }
  1840.  
  1841. /* Non zero if the insn is a move instruction which needs to be fixed. */
  1842.  
  1843. static
  1844. int
  1845. broken_move (insn)
  1846.      rtx insn;
  1847. {
  1848.   if (!INSN_DELETED_P (insn)
  1849.       && GET_CODE (insn) == INSN
  1850.       && GET_CODE (PATTERN (insn)) == SET)
  1851.     {
  1852.       rtx pat = PATTERN (insn);
  1853.       rtx src = SET_SRC (pat);
  1854.       rtx dst = SET_DEST (pat);
  1855.       enum machine_mode mode = GET_MODE (dst);
  1856.       if (dst == pc_rtx)
  1857.     return 0;
  1858.       return fixit (src, mode);
  1859.     }
  1860.   return 0;
  1861. }
  1862.  
  1863.  
  1864. /* Exported to toplev.c
  1865.  
  1866.    Scan the function looking for move instructions which have to be changed to
  1867.    pcrel loads and insert the literal tables. */
  1868.  
  1869. void
  1870. machine_dependent_reorg (first)
  1871.      rtx first;
  1872. {
  1873.   rtx insn;
  1874.   for (insn = first; insn; insn = NEXT_INSN (insn))
  1875.     {
  1876.       if (broken_move (insn))
  1877.     {
  1878.       /* This is a broken move instruction, scan ahead looking for
  1879.          a barrier to stick the constant table behind */
  1880.       rtx scan;
  1881.       rtx barrier = find_barrier (insn);
  1882.  
  1883.       /* Now find all the moves between the points and modify them */
  1884.       for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
  1885.         {
  1886.           if (broken_move (scan))
  1887.         {
  1888.           rtx pat = PATTERN (scan);
  1889.           rtx src = SET_SRC (pat);
  1890.           rtx dst = SET_DEST (pat);
  1891.           enum machine_mode mode = GET_MODE (dst);
  1892.           rtx lab;
  1893.           rtx newinsn;
  1894.           rtx newsrc;
  1895.           /* This is a broken move instruction, add it to the pool */
  1896.  
  1897.           if (mode == SImode && hi_const (src))
  1898.             {
  1899.               /* This is an HI source, clobber the dest to get the mode right too */
  1900.               mode = HImode;
  1901.               while (GET_CODE (dst) == SUBREG)
  1902.             dst = SUBREG_REG (dst);
  1903.               dst = gen_rtx (REG, HImode, REGNO (dst));
  1904.             }
  1905.           lab = add_constant (src, mode);
  1906.           newsrc = gen_rtx (MEM, mode,
  1907.                     gen_rtx (LABEL_REF, VOIDmode, lab));
  1908.  
  1909.           /* Build a jump insn wrapper around the move instead
  1910.              of an ordinary insn, because we want to have room for
  1911.              the target label rtx in fld[7], which an ordinary
  1912.              insn doesn't have. */
  1913.           newinsn = emit_jump_insn_after (gen_rtx (SET, VOIDmode,
  1914.                             dst, newsrc), scan);
  1915.           JUMP_LABEL (newinsn) = lab;
  1916.  
  1917.           /* But it's still an ordinary insn */
  1918.           PUT_CODE (newinsn, INSN);
  1919.  
  1920.           /* Kill old insn */
  1921.           delete_insn (scan);
  1922.           scan = newinsn;
  1923.         }
  1924.         }
  1925.       dump_table (barrier);
  1926.     }
  1927.     }
  1928. }
  1929.  
  1930. /* Called from the md file, set up the operands of a compare instruction */
  1931.  
  1932. void
  1933. from_compare (operands, code)
  1934.      rtx *operands;
  1935.      int code;
  1936. {
  1937.   if (code != EQ && code != NE)
  1938.     {
  1939.       /* Force args into regs, since we can't use constants here */
  1940.       sh_compare_op0 = force_reg (SImode, sh_compare_op0);
  1941.       if (sh_compare_op1 != const0_rtx)
  1942.     sh_compare_op1 = force_reg (SImode, sh_compare_op1);
  1943.     }
  1944.   operands[1] = sh_compare_op0;
  1945.   operands[2] = sh_compare_op1;
  1946. }
  1947.  
  1948. /* Non-zero if x is EQ or NE */
  1949.  
  1950. int
  1951. equality_operator (x, mode)
  1952.      rtx x;
  1953.      enum machine_mode mode;
  1954. {
  1955.   enum rtx_code code = GET_CODE (x);
  1956.   return (code == EQ || code == NE);
  1957. }
  1958.  
  1959.  
  1960. /* Add this function to the list of ones seen - temporary
  1961.    gross hack to try out bsrs. */
  1962. struct flist
  1963. {
  1964.   char *name;
  1965.   struct flist *next;
  1966. };
  1967. struct flist *head;
  1968.  
  1969. static void
  1970. add_function (name)
  1971.      char *name;
  1972. {
  1973.   struct flist *n = (struct flist *) xmalloc (sizeof (struct flist));
  1974.   int l = strlen (name) + 1;
  1975.   n->name = xmalloc (l);
  1976.   memcpy (n->name, name, l);
  1977.   n->next = head;
  1978.   head = n;
  1979. }
  1980.  
  1981. static int
  1982. seen_function (name)
  1983.      char *name;
  1984. {
  1985.   struct flist *p = head;
  1986.   for (p = head; p; p = p->next)
  1987.     {
  1988.       if (strcmp (p->name, name) == 0)
  1989.     return 1;
  1990.     }
  1991.   return 0;
  1992. }
  1993.  
  1994.  /* Framefull frame looks like:
  1995.  
  1996.     arg-5
  1997.     arg-4
  1998.     [ if current_function_anonymous_args
  1999.     arg-3
  2000.     arg-2
  2001.     arg-1
  2002.     arg-0 ]
  2003.     saved-fp
  2004.     saved-r10
  2005.     saved-r11
  2006.     saved-r12
  2007.     saved-pr
  2008.     local-n
  2009.     ..
  2010.     local-1
  2011.     local-0        <- fp points here
  2012.  
  2013.  
  2014.     If TARGET_SMALLCALL, then the preserved registers are pushed by a
  2015.     wrapper before the routine is entered, so the regs are always pushed
  2016.     and there are two pr's on the stack - the caller and the wrapper.
  2017.   */
  2018.  
  2019.  
  2020.  /* Code to generate prologue and epilogue sequences */
  2021.  
  2022.  
  2023. void
  2024. sh_expand_prologue ()
  2025. {
  2026.   int live_regs_mask;
  2027.   int d;
  2028.   extern tree current_function_decl;
  2029.   live_regs_mask = calc_live_regs (&d);
  2030.  
  2031.   /* We have pretend args if we had an object sent partially in registers
  2032.      and partially on the stack - eg a large structure */
  2033.   output_stack_adjust (-current_function_pretend_args_size);
  2034.  
  2035.   if (current_function_anonymous_args)
  2036.     {
  2037.       /* Push arg regs as if they'd been provided by caller in stack */
  2038.       int i;
  2039.       for (i = 0; i < NPARM_REGS; i++)
  2040.     {
  2041.       int rn = NPARM_REGS + FIRST_PARM_REG - i - 1;
  2042.       if (i > NPARM_REGS - current_function_args_info)
  2043.         break;
  2044.       push (rn);
  2045.       extra_push += 4;
  2046.     }
  2047.     }
  2048.   push_regs (live_regs_mask);
  2049.   output_stack_adjust (-get_frame_size ());
  2050.  
  2051.   if (frame_pointer_needed)
  2052.     {
  2053.       emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
  2054.     }
  2055.   if (TARGET_BSR)
  2056.     {
  2057.       add_function (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
  2058.     }
  2059.  
  2060.  
  2061. }
  2062.  
  2063. void
  2064. sh_expand_epilogue ()
  2065. {
  2066.   int live_regs_mask;
  2067.   int d;
  2068.   int i;
  2069.  
  2070.   live_regs_mask = calc_live_regs (&d);
  2071.  
  2072.   
  2073.   if (frame_pointer_needed)
  2074.     {
  2075.       emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
  2076.     }
  2077.   output_stack_adjust (get_frame_size ());
  2078.  
  2079.   /* Pop all the registers */
  2080.  
  2081.   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
  2082.     {
  2083.       int j = (FIRST_PSEUDO_REGISTER - 1) - i;
  2084.       if (live_regs_mask & (1 << j))
  2085.     {
  2086.       pop (j);
  2087.     }
  2088.     }
  2089.  
  2090.   output_stack_adjust (extra_push + current_function_pretend_args_size);
  2091.  
  2092.   extra_push = 0;
  2093.   current_function_pretend_args_size = 0;
  2094.   current_function_anonymous_args = 0;
  2095.   for (i = 0; i < 32; i++)
  2096.     shiftsyms[i] = 0;
  2097.  
  2098. }
  2099.  
  2100. /* Define the offset between two registers, one to be eliminated, and
  2101.    the other its replacement, at the start of a routine.  */
  2102.  
  2103. int
  2104. initial_elimination_offset (from, to)
  2105.      int from;
  2106.      int to;
  2107. {
  2108.   int regs_saved;
  2109.   int total_saved_regs_space;
  2110.   int total_auto_space = get_frame_size ();
  2111.  
  2112.   calc_live_regs (®s_saved);
  2113.   total_saved_regs_space = (regs_saved) * 4;
  2114.  
  2115.   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
  2116.     {
  2117.       return total_saved_regs_space + total_auto_space;
  2118.     }
  2119.   if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
  2120.     {
  2121.       return total_saved_regs_space + total_auto_space;
  2122.     }
  2123.   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
  2124.     {
  2125.       /* Initial gap between fp and sp is 0 */
  2126.       return 0;
  2127.     }
  2128.   abort ();
  2129. }
  2130.  
  2131. /* Handle machine specific pragmas to be semi-compatible with Hitachi
  2132.    compiler  */
  2133.  
  2134. int
  2135. handle_pragma (file)
  2136.      FILE *file;
  2137. {
  2138.   int c;
  2139.   char pbuf[200];
  2140.   int psize = 0;
  2141.  
  2142.   c = getc (file);
  2143.   while (c == ' ' || c == '\t')
  2144.     c = getc (file);
  2145.  
  2146.   if (c == '\n' || c == EOF)
  2147.     return c;
  2148.  
  2149.   while (psize < sizeof (pbuf) - 1 && c != '\n')
  2150.     {
  2151.       pbuf[psize++] = c;
  2152.       if (psize == 9 && strncmp (pbuf, "interrupt", 9) == 0)
  2153.     {
  2154.       pragma_interrupt = 1;
  2155.       return ' ';
  2156.     }
  2157.       if (psize == 5 && strncmp (pbuf, "trapa", 5) == 0)
  2158.     {
  2159.       pragma_interrupt = pragma_trapa = 1;
  2160.       return ' ';
  2161.     }
  2162.       c = getc (file);
  2163.     }
  2164.   return c;
  2165. }
  2166.  
  2167. /* insn expand helpers */
  2168.  
  2169. /* Emit insns to perform a call.
  2170.    If TARGET_SHORTADDR then use a bsr. If TARGET_SMALLCALL, then load the
  2171.    target address into r1 and call __saveargs, otherwise
  2172.    perform the standard call sequence */
  2173.  
  2174. void
  2175. expand_acall (isa_retval, operands)
  2176.      int isa_retval;
  2177.      rtx *operands;
  2178. {
  2179.   rtx call;
  2180.   rtx ret = operands[0];
  2181.   rtx call_target = operands[isa_retval + 0];
  2182.   rtx numargs = operands[isa_retval + 1];
  2183.  
  2184.   if (TARGET_BSR && bsr_operand (call_target, VOIDmode))
  2185.     {
  2186.       call = gen_rtx (CALL, VOIDmode, call_target, numargs);
  2187.     }
  2188.   else
  2189.     {
  2190.       if (GET_CODE (call_target) == MEM)
  2191.     {
  2192.       call_target = force_reg (Pmode,
  2193.                    XEXP (call_target, 0));
  2194.     }
  2195.       if (TARGET_SMALLCALL)
  2196.     {
  2197.       rtx tmp = gen_reg_rtx (SImode);
  2198.       rtx r1 = gen_rtx (REG, SImode, 1);
  2199.       emit_move_insn (tmp, gen_rtx (SYMBOL_REF, SImode, "__saveargs"));
  2200.       emit_move_insn (r1, call_target);
  2201.       emit_insn (gen_rtx (USE, VOIDmode, r1));
  2202.       call_target = tmp;
  2203.     }
  2204.  
  2205.       call = gen_rtx (CALL, VOIDmode, gen_rtx (MEM, SImode, call_target), numargs);
  2206.     }
  2207.   if (isa_retval)
  2208.     {
  2209.       call = gen_rtx (SET, VOIDmode, ret, call);
  2210.     }
  2211.  
  2212.   emit_call_insn (gen_rtx (PARALLEL, VOIDmode,
  2213.                gen_rtvec (2,
  2214.                       call,
  2215.           gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 17)))));
  2216.  
  2217. }
  2218.  
  2219.  
  2220. /* Predicates used by the templates */
  2221.  
  2222.  
  2223. /* Returns 1 if OP can be source of a simple move operation.
  2224.    Same as general_operand, but a LABEL_REF is valid, PRE_DEC is
  2225.    invalid as are subregs of system registers. */
  2226.  
  2227. int
  2228. general_movsrc_operand (op, mode)
  2229.      rtx op;
  2230.      enum machine_mode mode;
  2231. {
  2232.   /* Any MEM(label_ref) is ok, that's a pcrel load */
  2233.   if (GET_CODE (op) == MEM
  2234.       && GET_CODE (XEXP (op, 0)) == LABEL_REF)
  2235.     return 1;
  2236.  
  2237.   if (GET_CODE (op) == MEM)
  2238.     {
  2239.       rtx inside = XEXP (op, 0);
  2240.       if (GET_CODE (inside) == CONST)
  2241.     inside = XEXP (inside, 0);
  2242.  
  2243.       if (GET_CODE (inside) == LABEL_REF)
  2244.     return 1;
  2245.  
  2246.       if (GET_CODE (inside) == PLUS
  2247.       && GET_CODE (XEXP (inside,0)) == LABEL_REF
  2248.       && GET_CODE (XEXP (inside,1)) == CONST_INT)
  2249.     return 1;
  2250.       
  2251.       /* No post inc allowed */
  2252.       if (GET_CODE (inside) == POST_DEC
  2253.       || GET_CODE (inside) == PRE_INC
  2254.       || GET_CODE (inside) == PRE_DEC)
  2255.     return 0;
  2256.  
  2257.       /* Can't do that with large modes */
  2258.       if (GET_CODE (inside) == POST_INC
  2259.       && GET_MODE_SIZE (mode) > 4)
  2260.     return 0;
  2261.     }
  2262.  
  2263.   if ((mode == QImode || mode == HImode)
  2264.       && (GET_CODE (op) == SUBREG
  2265.       && GET_CODE (XEXP (op, 0)) == REG
  2266.       && system_reg_operand (XEXP (op, 0), mode)))
  2267.     return 0;
  2268.  
  2269.   if (GET_CODE (op) == CONST_INT)
  2270.     {
  2271.       int i = INTVAL (op);
  2272.       return CONST_OK_FOR_I (i);
  2273.     }
  2274.   return general_operand (op, mode);
  2275. }
  2276.  
  2277.  
  2278. /* Returns 1 if OP can be a destination of a move.
  2279.    Same as general_operand, but no preinc allowed.  */
  2280.  
  2281. int
  2282. general_movdst_operand (op, mode)
  2283.      rtx op;
  2284.      enum machine_mode mode;
  2285. {
  2286.   /* No pre dec allowed */
  2287.   if (GET_CODE (op) == MEM
  2288.       && (GET_CODE (XEXP (op, 0)) == PRE_INC
  2289.       || GET_CODE (XEXP (op, 0)) == POST_INC
  2290.       || GET_CODE (XEXP (op, 0)) == POST_DEC))
  2291.     return 0;
  2292.  
  2293.   if (GET_CODE (op) == MEM
  2294.       && GET_CODE (XEXP (op, 0)) == PRE_DEC
  2295.       && GET_MODE_SIZE (mode) > 4)
  2296.     return 0;
  2297.  
  2298.   return general_operand (op, mode);
  2299. }
  2300.  
  2301.  
  2302.  
  2303. /* Returns 1 if OP is valid destination for a bsr.  */
  2304.  
  2305. int
  2306. bsr_operand (op, mode)
  2307.      rtx op;
  2308.      enum machine_mode mode;
  2309. {
  2310.   if (TARGET_BSR)
  2311.     {
  2312.       if (GET_CODE (op) == SYMBOL_REF)
  2313.     {
  2314.       if (!strcmp (XSTR (op, 0),
  2315.               IDENTIFIER_POINTER (DECL_NAME (current_function_decl))))
  2316.         return 1;
  2317.       return (seen_function (XSTR (op, 0)));
  2318.     }
  2319.     }
  2320.   return 0;
  2321. }
  2322.  
  2323. /* Returns 1 if OP is an immediate ok for a byte index.  */
  2324.  
  2325. int
  2326. byte_index_operand (op, mode)
  2327.      rtx op;
  2328.      enum machine_mode mode;
  2329. {
  2330.   return (GET_CODE (op) == CONST_INT
  2331.       && INTVAL (op) >= 0
  2332.       && INTVAL (op) <= 15);
  2333. }
  2334.  
  2335. /* Returns 1 if OP is a pop operand.   */
  2336.  
  2337. int
  2338. pop_operand (op, mode)
  2339.      rtx op;
  2340.      enum machine_mode mode;
  2341. {
  2342.   if (GET_CODE (op) != MEM)
  2343.     return 0;
  2344.  
  2345.   if (GET_MODE (op) != mode)
  2346.     return 0;
  2347.  
  2348.   op = XEXP (op, 0);
  2349.  
  2350.   if (GET_CODE (op) != POST_INC)
  2351.     return 0;
  2352.  
  2353.   return XEXP (op, 0) == stack_pointer_rtx;
  2354. }
  2355.  
  2356.  
  2357. /* Returns 1 if OP is a normal arithmetic register.  */
  2358.  
  2359. int
  2360. arith_reg_operand (op, mode)
  2361.      rtx op;
  2362.      enum machine_mode mode;
  2363. {
  2364.   if (register_operand (op, mode))
  2365.     {
  2366.       if (GET_CODE (op) == REG)
  2367.     return (REGNO (op) != T_REG
  2368.         && REGNO (op) != PR_REG);
  2369.       return 1;
  2370.     }
  2371.   return 0;
  2372. }
  2373.  
  2374. /* Returns 1 if OP is MACL, MACH or PR.  */
  2375.  
  2376. int
  2377. system_reg_operand (op, mode)
  2378.      rtx op;
  2379.      enum machine_mode mode;
  2380. {
  2381.   if (GET_CODE (op) == REG)
  2382.     {
  2383.       switch (REGNO (op))
  2384.     {
  2385.     case PR_REG:
  2386.     case MACL_REG:
  2387.     case MACH_REG:
  2388.       return 1;
  2389.     }
  2390.     }
  2391.   return 0;
  2392. }
  2393.  
  2394.  
  2395. /* Returns 1 if OP is a valid source operand for an arithmetic insn.  */
  2396.  
  2397. int
  2398. arith_operand (op, mode)
  2399.      rtx op;
  2400.      enum machine_mode mode;
  2401. {
  2402.   if (arith_reg_operand (op, mode))
  2403.     return 1;
  2404.  
  2405.   if (GET_CODE (op) == CONST_INT)
  2406.     {
  2407.       if (CONST_OK_FOR_I (INTVAL (op)))
  2408.     return 1;
  2409.     }
  2410.   return 0;
  2411. }
  2412.  
  2413.  
  2414. /* Returns 1 if OP is a valid source operand for a logical operation. */
  2415.  
  2416. int
  2417. logical_operand (op, mode)
  2418.      rtx op;
  2419.      enum machine_mode mode;
  2420. {
  2421.   if (arith_reg_operand (op, mode))
  2422.     return 1;
  2423.  
  2424.   if (GET_CODE (op) == CONST_INT)
  2425.     {
  2426.       if (CONST_OK_FOR_L (INTVAL (op)))
  2427.     return 1;
  2428.     }
  2429.   return 0;
  2430. }
  2431.  
  2432. /* Returns 1 if OP is a valid operand for a MAC instruction,
  2433.    either a register or indirect memory.  For now we don't
  2434.    try and recognise a mac insn */
  2435.  
  2436. int
  2437. mac_operand (op, mode)
  2438.      rtx op;
  2439.      enum machine_mode mode;
  2440. {
  2441.   if (arith_reg_operand (op, mode))
  2442.     return 1;
  2443. #if 0
  2444.   Turned off till mac is understood
  2445.   if (GET_CODE (op) == MEM)
  2446.     return 1;
  2447. #endif
  2448.   return 0;
  2449. }
  2450.  
  2451. /* Determine where to put an argument to a function.
  2452.    Value is zero to push the argument on the stack,
  2453.    or a hard register in which to store the argument.
  2454.  
  2455.    MODE is the argument's machine mode.
  2456.    TYPE is the data type of the argument (as a tree).
  2457.     This is null for libcalls where that information may
  2458.     not be available.
  2459.    CUM is a variable of type CUMULATIVE_ARGS which gives info about
  2460.     the preceding args and about the function being called.
  2461.    NAMED is nonzero if this argument is a named parameter
  2462.     (otherwise it is an extra parameter matching an ellipsis).  */
  2463.  
  2464. rtx
  2465. sh_function_arg (cum, mode, type, named)
  2466.      CUMULATIVE_ARGS cum;
  2467.      enum machine_mode mode;
  2468.      tree type;
  2469.      int named;
  2470. {
  2471.   if (named)
  2472.     {
  2473.       int rr = (ROUND_REG ((cum), (mode)));
  2474.  
  2475.       if (rr < NPARM_REGS)
  2476.     {
  2477.       return (((type) == 0 || !TREE_ADDRESSABLE ((tree) (type)))
  2478.           && ((type) == 0 || (mode) != BLKmode
  2479.               || (TYPE_ALIGN ((type)) % PARM_BOUNDARY == 0))
  2480.           ? gen_rtx (REG, (mode),
  2481.                  (FIRST_PARM_REG + rr)) 
  2482.           : 0);
  2483.  
  2484.     }
  2485.     }
  2486.   return 0;
  2487. }
  2488.  
  2489. /* For an arg passed partly in registers and partly in memory,
  2490.    this is the number of registers used.
  2491.    For args passed entirely in registers or entirely in memory, zero.
  2492.    Any arg that starts in the first 4 regs but won't entirely fit in them
  2493.    needs partial registers on the SH.  */
  2494.  
  2495. int
  2496. sh_function_arg_partial_nregs (CUM, MODE, TYPE, NAMED)
  2497.      CUMULATIVE_ARGS CUM;
  2498.      enum machine_mode MODE;
  2499.      tree TYPE;
  2500.      int NAMED;
  2501. {
  2502.   if ((CUM) < NPARM_REGS)
  2503.     {
  2504.       if (((TYPE) == 0 || !TREE_ADDRESSABLE ((tree) (TYPE)))
  2505.       && ((TYPE) == 0 || (TYPE_ALIGN ((TYPE)) % PARM_BOUNDARY == 0))
  2506.       && ((CUM) + ((MODE) == BLKmode
  2507.                ? ROUND_ADVANCE (int_size_in_bytes (TYPE))
  2508.           : ROUND_ADVANCE (GET_MODE_SIZE (MODE))) - NPARM_REGS > 0))
  2509.     {
  2510.       return NPARM_REGS - CUM;
  2511.     }
  2512.     }
  2513.   return 0;
  2514. }
  2515.  
  2516. /* Turn this on to recognise shift insns which aren't supported in the
  2517.    hardware.  This will allow the combiner to notice more patterns,
  2518.    but the down side is that the asm outputter will have to emit
  2519.    several instructions for each shift which isn't possible in the
  2520.    hardware, this makes scheduling perform badly .*/ 
  2521.  
  2522. int fake_shift()
  2523. {
  2524.   return 0;
  2525. }
  2526.